<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<!-- 4、 实现一个 memorize 方法，记忆函数上次运行的结果，使得连续两次调用，如果参数相同，则返回上次的执行结果，不执行函数体；如果参数不同，则执行。函数参数限1个。
function memorize(fn) {
 // 你的代码
}
```
使用示例：
```
const sayHello = memorize((name) => {
    console.log(`ok, ${name}`);
    return `ok, ${name}`;
});

sayHello('B'); // 首次执行，打印 "ok B", 返回 "ok B"
sayHello('B'); // 第二次执行，不打印直接返回 "ok B" -->


<body>
    <div>test13-4</div>
    <script>
        const sayHello = memorize((name) => {
            console.log(`ok, ${name}`);
            return `ok, ${name}`;
        });
        function memorize(f) {
            var cache = {};
            console.log(cache)
            return function () {
                var key = arguments.length + Array.prototype.join.call(arguments, ",");
                if (key in cache) {
                    return cache[key]
                }
                else return cache[key] = f.apply(this, arguments)
                // this在这里没什么用，等同于f(Array.from(arguments)) 或者 f.apply(arguments)
                // else return cache[key] = f(Array.from(arguments))
            }
        }
        sayHello('B'); // 首次执行，打印 "ok B", 返回 "ok B"
        sayHello('B'); // 第二次执行，不打印直接返回 "ok B" 
    </script>
</body>

</html>
适用场景
我们以斐波那契数列为例：
var count = 0;
var fibonacci = function(n){
    count++;
    return n < 2? n : fibonacci(n-1) + fibonacci(n-2);
};
for (var i = 0; i <= 10; i++){
    fibonacci(i)
}

console.log(count) // 453复制代码我们会发现最后的 count 数为 453，也就是说 fibonacci 函数被调用了 453 次！也许你会想，我只是循环到了 10，为什么就被调用了这么多次，所以我们来具体分析下：
当执行 fib(0) 时，调用 1 次

当执行 fib(1) 时，调用 1 次

当执行 fib(2) 时，相当于 fib(1) + fib(0) 加上 fib(2) 本身这一次，共 1 + 1 + 1 = 3 次

当执行 fib(3) 时，相当于 fib(2) + fib(1) 加上 fib(3) 本身这一次，共 3 + 1 + 1 = 5 次

当执行 fib(4) 时，相当于 fib(3) + fib(2) 加上 fib(4) 本身这一次，共 5 + 3 + 1 = 9 次

当执行 fib(5) 时，相当于 fib(4) + fib(3) 加上 fib(5) 本身这一次，共 9 + 5 + 1 = 15 次

当执行 fib(6) 时，相当于 fib(5) + fib(4) 加上 fib(6) 本身这一次，共 15 + 9 + 1 = 25 次

当执行 fib(7) 时，相当于 fib(6) + fib(5) 加上 fib(7) 本身这一次，共 25 + 15 + 1 = 41 次

当执行 fib(8) 时，相当于 fib(7) + fib(6) 加上 fib(8) 本身这一次，共 41 + 25 + 1 = 67 次

当执行 fib(9) 时，相当于 fib(8) + fib(7) 加上 fib(9) 本身这一次，共 67 + 41 + 1 = 109 次

当执行 fib(10) 时，相当于 fib(9) + fib(8) 加上 fib(10) 本身这一次，共 109 + 67 + 1 = 177 次复制代码所以执行的总次数为：177 + 109 + 67 + 41 + 25 + 15 + 9 + 5 + 3 + 1 + 1 = 453 次！
如果我们使用函数记忆呢？
var count = 0;
var fibonacci = function(n) {
    count++;
    return n < 2 ? n : fibonacci(n - 1) + fibonacci(n - 2);
};

fibonacci = memorize(fibonacci)

for (var i = 0; i <= 10; i++) {
    fibonacci(i)
}

console.log(count) // 12复制代码我们会发现最后的总次数为 12 次，因为使用了函数记忆，调用次数从 453 次降低为了 12 次!
兴奋的同时不要忘记思考：为什么会是 12 次呢？
从 0 到 10 的结果各储存一遍，应该是 11 次呐？咦，那多出来的一次是从哪里来的？
所以我们还需要认真看下我们的写法，在我们的写法中，其实我们用生成的 fibonacci 函数覆盖了原本了 fibonacci 函数，当我们执行 fibonacci(0) 时，执行一次函数，cache 为 {0: 0}，但是当我们执行 fibonacci(2) 的时候，执行 fibonacci(1) + fibonacci(0)，因为 fibonacci(0) 的值为 0，!cache[address] 的结果为 true，又会执行一次 fibonacci 函数。原来，多出来的那一次是在这里！
var memoizer = function (func) {
    let memo = [];
    return function (n) {
        if (memo[n] == undefined) {
            memo[n] = func(n)
        }
        return memo[n]
    }
};
var fibonacci=memoizer(function(n){
    if (n == 1 || n == 2) {
        return 1
    };
    return fibonacci(n - 2) + fibonacci(n - 1);
})
fibonacci(30)